﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using IRCPhase1Tester.Tests;
using System.Threading;
using Amazon.SimpleDB;
using Amazon;
using Amazon.SimpleDB.Model;
using System.Text.RegularExpressions;

namespace IRCPhase1Tester
{
    public partial class MainForm : Form
    {
        private Thread runThread;
        private Thread uploadThread;

        delegate void UpdateControl(string message);

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            ListBox.CheckForIllegalCrossThreadCalls = false;
            ProgressBar.CheckForIllegalCrossThreadCalls = false;
            Session.Instance.PortNumber = 9090;
        }

        private void AddNewListItem(string message)
        {
            this.lstTestingProgress.Items.Add(message);
        }

        private void UpdateLastListItem(string appendedMessage)
        {
            string message = (string)this.lstTestingProgress.Items[this.lstTestingProgress.Items.Count - 1];
            this.lstTestingProgress.Items[this.lstTestingProgress.Items.Count - 1] = message + appendedMessage;
        }

        private void RunTest(ITest test)
        {
            TestingContext context;

            AddNewListItem("Running " + test.Title() + " Test... ");
            context = new TestingContext(test);
            UpdateLastListItem(context.ExecuteTest() ? "Passed" : "Failed");
        }

        private void RunTests()
        {
            RunTest(new UserCommandHappy());
            RunTest(new UserCommandMissingParams());
            RunTest(new NickCommandHappy());
            RunTest(new NickCommandNickInUse());
            RunTest(new NickCommandNoNick());
            RunTest(new UnknownCommand());
            RunTest(new UserCommandAlreadyRegistered());
            RunTest(new Tests.PrivmsgCommandHappy());
            RunTest(new Tests.PrivmsgCommandNoRecipient());
            RunTest(new Tests.PrivmsgCommandNoSuchNick());
            RunTest(new Tests.PrivmsgCommandNoTextToSend());
            RunTest(new Tests.PrivmsgCommandUnregistered());
            RunTest(new Tests.PrivmsgCommandUnregisteredWithNickCommand());
            RunTest(new Tests.PrivmsgCommandUnregisteredWithUserCommand());
            RunTest(new Tests.PrivmsgCommandMultipleTargetsHappy());
            RunTest(new Tests.PrivmsgCommandMultipleTargetsNoSuchNick());
            RunTest(new Tests.PrivmsgCommandBackAndForth());
            RunTest(new Tests.PrivmsgCommandLoad());
            RunTest(new Tests.PrivmsgCommandSendToUnregisteredClient());

            MessageBox.Show("Finished all tests, " + Session.Instance.PassedTests.Count.ToString() + " passed test(s), " +
                Session.Instance.FailedTests.Count.ToString() + " failed test(s).");
        }

        private void btnRunTests_Click(object sender, EventArgs e)
        {
            bool error = false;

            if (txtServerPath.Text == string.Empty)
            {
                errProvider.SetError(txtServerPath, "Browse for the server exe first.");
                error = true;
            }
            else
            {
                errProvider.SetError(txtServerPath, null);
            }

            if (txtSolutionPath.Text == string.Empty)
            {
                errProvider.SetError(txtSolutionPath, "Browse for the solution file first.");
                error = true;
            }
            else
            {
                errProvider.SetError(txtSolutionPath, null);
            }

            if (txtSecretKey.Text == string.Empty)
            {
                errProvider.SetError(txtSecretKey, "Enter your secret key first.");
                error = true;
            }
            else
            {
                errProvider.SetError(txtSecretKey, null);
            }

            if (error)
                return;

            Session.Instance.FailedTests.Clear();
            Session.Instance.PassedTests.Clear();
            this.lstTestingProgress.Items.Clear();
            runThread = new Thread(new ThreadStart(RunTests));
            runThread.Start();
        }

        private void btnBrowseServer_Click(object sender, EventArgs e)
        {
            if (this.ofdServer.ShowDialog() == DialogResult.OK)
            {
                this.txtServerPath.Text = this.ofdServer.FileName;
                Session.Instance.ServerPath = this.ofdServer.FileName;
            }
        }

        private void btnBrowseSolution_Click(object sender, EventArgs e)
        {
            if (this.ofdSolution.ShowDialog() == DialogResult.OK)
            {
                this.txtSolutionPath.Text = this.ofdSolution.FileName;
                GetSolutionID();
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                runThread.Abort();
                uploadThread.Abort();
            }
            catch
            {
            }
        }

        private void btnUpload_Click(object sender, EventArgs e)
        {
            if (Session.Instance.FailedTests.Count == 0 && Session.Instance.PassedTests.Count == 0)
            {
                MessageBox.Show("Nothing to upload. Please run the tests first.");
                return;
            }
            Session.Instance.SecretKey = this.txtSecretKey.Text;
            uploadThread = new Thread(new ThreadStart(Upload));
            uploadThread.Start();
        }

        private string GetSolutionID()
        {
            string solutionFile = this.txtSolutionPath.Text;
            string[] fileLines = System.IO.File.ReadAllLines(solutionFile);

            foreach (string line in fileLines)
            {
                Regex regex = new Regex("Project\\(\"{.*}\"\\).*\"{(.*)}\"");
                Match match = regex.Match(line);
                bool isSuccess = match.Success;

                if (isSuccess)
                {
                    return match.Groups[1].Value;
                }
            }

            throw new Exception();
        }

        private void Upload()
        {
            string solutionId = string.Empty;

            try
            {
                solutionId = GetSolutionID();
            }
            catch
            {
                MessageBox.Show("Failed to parse your code, make sure you are pointing at the IRC Project Solution");
                return;
            }

            try
            {
                AmazonSimpleDB sdb = AWSClientFactory.CreateAmazonSimpleDBClient("AKIAJD3S26PKREHEHZTQ", "BnT1LDus1L+lKve08HufCaE+0rNz113jN8Bjhh71");
                string domainName = "IRCPhase1Results";

                progressUpload.Value = 10;

                String itemNameOne = Guid.NewGuid().ToString();
                PutAttributesRequest putAttributesActionOne = new PutAttributesRequest().WithDomainName(domainName).WithItemName(itemNameOne);
                List<ReplaceableAttribute> attributesOne = putAttributesActionOne.Attribute;
                attributesOne.Add(new ReplaceableAttribute().WithName("SecretKey").WithValue(Session.Instance.SecretKey));
                string failedTests = string.Join(",", Session.Instance.FailedTests.Select(t => t.TestID().ToString()).ToArray());
                attributesOne.Add(new ReplaceableAttribute().WithName("FailedTests").WithValue(failedTests));
                string passedTests = string.Join(",", Session.Instance.PassedTests.Select(t => t.TestID().ToString()).ToArray());
                attributesOne.Add(new ReplaceableAttribute().WithName("PassedTests").WithValue(passedTests));
                attributesOne.Add(new ReplaceableAttribute().WithName("Date").WithValue(DateTime.Now.ToString()));
                attributesOne.Add(new ReplaceableAttribute().WithName("SolutionGUID").WithValue(solutionId));
                attributesOne.Add(new ReplaceableAttribute().WithName("Version").WithValue("1.0"));
                sdb.PutAttributes(putAttributesActionOne);

                progressUpload.Value = 20;

                while (progressUpload.Value < 100)
                {
                    progressUpload.Value++;
                    System.Threading.Thread.Sleep(100);
                    if (progressUpload.Value > 50 && progressUpload.Value < 60)
                        System.Threading.Thread.Sleep(400);
                }

                MessageBox.Show("Uploaded Successfully");
            }
            catch
            {
                MessageBox.Show("Failed to Upload", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                progressUpload.Value = 0;
            }
        }
    }
}
